package com.dituhui.gps.vo;

import java.util.Calendar;
import java.util.Date;

import net.sf.json.JSONObject;

import org.apache.log4j.Logger;

import com.dituhui.tool.gis.Point;
import com.dituhui.tool.util.DateUtil;
import com.dituhui.tool.util.StringUtil;

/**
 * GPS点
 * 
 * @author liweigu
 * 
 */
public class GPSPoint extends Point {
	private static final Logger LOGGER = Logger.getLogger(GPSPoint.class);
	// GPS坐标保留小数点后6位
	public static String CoordFormat = "#.000000";
	// 速度保留小数点后2位
	private static String SpeedFormat = "#.00";

	// 修正后X坐标
	private double reviseX;

	// 修正后Y坐标
	private double reviseY;

	// 车牌号
	private String plateNumber;

	// 账号id
	private String accountId;

	// 组织id
	private String groupId;

	// 登录手机号
	private String loginMobile;

	// 地址
	private String address;

	// GPS时间
	private Date gpsTime;

	// 上传时间
	private Date uploadTime;

	// 方向
	private double direction;

	// 速度
	private double speed;

	// 限速
	private double speedLimit;

	// 顺序号（处理飞点用）
	private int order;

	// 标记。默认值为0，即正常点；1代表停滞点。
	private int gpsTag;

	// 车辆状态。
	// 值是0、1、2、3、4、5，分别代表未知状态、正常行驶（同时在线）、停留（同时在线）、停留超时（同时在线）、超速（同时在线）、离线（即信号丢失）。默认值是0。
	private int status;

	// 精确度
	private int accuracy;

	// 删除标记。“0”表示未删除；去重、去除非当天坐标。
	private String deleteTag;

	public GPSPoint(double x, double y) {
		super(x, y);
	}

	/**
	 * 复制GPSPoint对象。日期字段是索引引用。
	 * 
	 * @param gpsPoint GPSPoint对象
	 */
	public GPSPoint(GPSPoint gpsPoint) {
		super(gpsPoint);

		if (gpsPoint.accountId != null) {
			this.accountId = new String(gpsPoint.accountId);
		}
		if (gpsPoint.groupId != null) {
			this.groupId = new String(gpsPoint.groupId);
		}
		if (gpsPoint.loginMobile != null) {
			this.loginMobile = new String(gpsPoint.loginMobile);
		}
		if (gpsPoint.address != null) {
			this.address = new String(gpsPoint.address);
		}
		// TODO:拷贝日期对象
		this.gpsTime = gpsPoint.gpsTime;
		this.uploadTime = gpsPoint.uploadTime;
		this.reviseX = gpsPoint.reviseX;
		this.reviseY = gpsPoint.reviseY;
		this.gpsTag = gpsPoint.gpsTag;
		this.speed = gpsPoint.speed;
		this.speedLimit = gpsPoint.speedLimit;
		if (gpsPoint.plateNumber != null) {
			this.plateNumber = new String(gpsPoint.plateNumber);
		}
		this.status = gpsPoint.status;
		this.direction = gpsPoint.direction;
		if (gpsPoint.deleteTag != null) {
			this.deleteTag = new String(gpsPoint.deleteTag);
		}
	}

	public String getAccountId() {
		return this.accountId;
	}

	public void setAccountId(String accountId) {
		this.accountId = accountId;
	}

	public String getGroupId() {
		return this.groupId;
	}

	public void setGroupId(String groupId) {
		this.groupId = groupId;
	}

	public String getLoginMobile() {
		return this.loginMobile;
	}

	public void setLoginMobile(String loginMobile) {
		this.loginMobile = loginMobile;
	}

	public String getAddress() {
		return this.address;
	}

	public void setAddress(String address) {
		this.address = address;
	}

	public String getPlateNumber() {
		return this.plateNumber;
	}

	public void setPlateNumber(String plateNumber) {
		this.plateNumber = plateNumber;
	}

	public Date getGPSTime() {
		return gpsTime;
	}

	public void setGPSTime(Date gpsTime) {
		this.gpsTime = gpsTime;
	}

	public Date getUploadTime() {
		return uploadTime;
	}

	public void setUploadTime(Date uploadTime) {
		this.uploadTime = uploadTime;
	}

	/**
	 * 返回纠偏后的X坐标。如果纠偏后的X坐标是0，则返回原始X坐标。
	 * 
	 * @return 纠偏后的X坐标
	 */
	public double getReviseX() {
		return (this.reviseX > 1) ? this.reviseX : this.x;
	}

	public void setReviseX(double reviseX) {
		this.reviseX = reviseX;
	}

	/**
	 * 返回纠偏后的Y坐标。如果纠偏后的Y坐标是0，则返回原始Y坐标。
	 * 
	 * @return 纠偏后的Y坐标
	 */
	public double getReviseY() {
		return (this.reviseY > 1) ? this.reviseY : this.y;
	}

	public void setReviseY(double reviseY) {
		this.reviseY = reviseY;
	}

	public double getDirection() {
		return this.direction;
	}

	public void setDirection(double direction) {
		this.direction = direction;
	}

	public int getOrder() {
		return this.order;
	}

	public void setOrder(int order) {
		this.order = order;
	}

	public int getGpsTag() {
		return this.gpsTag;
	}

	public void setGpsTag(int gpsTag) {
		this.gpsTag = gpsTag;
	}

	public double getSpeed() {
		return this.speed;
	}

	public void setSpeed(double speed) {
		this.speed = speed;
	}

	public double getSpeedLimit() {
		return this.speedLimit;
	}

	public void setSpeedLimit(double speedLimit) {
		this.speedLimit = speedLimit;
	}

	public int getStatus() {
		return this.status;
	}

	public void setStatus(int status) {
		this.status = status;
	}

	public int getAccuracy() {
		return this.accuracy;
	}

	public void setAccuracy(int accuracy) {
		this.accuracy = accuracy;
	}

	public String getDeleteTag() {
		return this.deleteTag;
	}

	public void setDeleteTag(String deleteTag) {
		this.deleteTag = deleteTag;
	}

	@Override
	/**
	 * 转换为字符串，格式是json。
	 */
	public String toString() {
		String accountIdKey = "aid";
		String groupIdKey = "groupId";
		String loginMobileKey = "loginMobile";
		String addressKey = "address";
		String gpstimeKey = "gpstime";
		String uploadTimeKey = "uploadTime";
		String xKey = "x";
		String yKey = "y";
		String reviseXKey = "reviseX";
		String reviseYKey = "reviseY";
		String gpsTagKey = "gpsTag";
		String speedKey = "speed";
		String speedLimitKey = "speedLimit";
		String plateNumberKey = "plateNumber";
		String statusKey = "status";
		String accuracyKey = "accuracy";
		String directionKey = "direction";
		String deleteTagKey = "deleteTag";

		JSONObject jsonObject = new JSONObject();
		jsonObject.put(accountIdKey, this.getAccountId());
		jsonObject.put(groupIdKey, this.getGroupId());
		jsonObject.put(loginMobileKey, this.getLoginMobile());
		jsonObject.put(addressKey, this.getAddress());
		Calendar calendar = Calendar.getInstance();
		if (this.getGPSTime() != null) {
			// 转为"yyyyMMddHHmmss"格式
			calendar.clear();
			calendar.setTime(this.getGPSTime());
			try {
				String gpsDataTime = DateUtil.getGPSTimeFormat().format(calendar.getTime());
				jsonObject.put(gpstimeKey, gpsDataTime);
			} catch (Exception e) {
				String message = "解析gpstime发生异常。gpsTime=" + this.getGPSTime();
				LOGGER.info(message, e);
			}
		}
		if (this.getUploadTime() != null) {
			// 转为"yyyyMMddHHmmss"格式
			calendar.clear();
			calendar.setTime(this.getUploadTime());
			try {
				String gpsUploadTime = DateUtil.getGPSTimeFormat().format(calendar.getTime());
				jsonObject.put(uploadTimeKey, gpsUploadTime);
			} catch (Exception e) {
				String message = "解析uploadTime发生异常。uploadTime=" + this.getUploadTime();
				LOGGER.info(message, e);
			}
		}
		jsonObject.put(xKey, this.getX());
		jsonObject.put(yKey, this.getY());
		jsonObject.put(reviseXKey, this.getReviseX());
		jsonObject.put(reviseYKey, this.getReviseY());
		if (this.getGpsTag() != 0) {
			jsonObject.put(gpsTagKey, this.getGpsTag());
		}
		if (this.getSpeed() > 0) {
			jsonObject.put(speedKey, this.getSpeed());
		}
		if (this.getSpeedLimit() > 0) {
			jsonObject.put(speedLimitKey, this.getSpeedLimit());
		}
		jsonObject.put(plateNumberKey, this.getPlateNumber());
		jsonObject.put(statusKey, this.getStatus());
		jsonObject.put(accuracyKey, this.getAccuracy());
		if (this.getDirection() > 0) {
			jsonObject.put(directionKey, this.getDirection());
		}
		if (this.getDeleteTag() != null) {
			jsonObject.put(deleteTagKey, this.getDeleteTag());
		}
		return jsonObject.toString();
	}

	public String toCSVString() {
		StringBuilder csvStringBuilder = new StringBuilder();
		String split = StringUtil.COMMA;

		// index:0
		csvStringBuilder.append(this.getAccountId());
		csvStringBuilder.append(split);
		// index:1
		csvStringBuilder.append(this.getLoginMobile());
		csvStringBuilder.append(split);
		// index:2
		csvStringBuilder.append(this.getAddress());
		csvStringBuilder.append(split);
		String gpsDataTime = "";
		Calendar calendar = Calendar.getInstance();
		if (this.getGPSTime() != null) {
			// 转为"yyyyMMddHHmmss"格式
			calendar.clear();
			calendar.setTime(this.getGPSTime());
			try {
				gpsDataTime = DateUtil.getGPSTimeFormat().format(calendar.getTime());
			} catch (Exception e) {
				String message = "解析gpstime发生异常。gpsTime=" + this.getGPSTime();
				LOGGER.info(message, e);
			}
		}
		// index:3
		csvStringBuilder.append(gpsDataTime);
		csvStringBuilder.append(split);
		String gpsUploadTime = "";
		if (this.getUploadTime() != null) {
			// 转为"yyyyMMddHHmmss"格式
			calendar.clear();
			calendar.setTime(this.getUploadTime());
			try {
				gpsUploadTime = DateUtil.getGPSTimeFormat().format(calendar.getTime());
			} catch (Exception e) {
				String message = "解析uploadTime发生异常。uploadTime=" + this.getUploadTime();
				LOGGER.info(message, e);
			}
		}
		// index:4
		csvStringBuilder.append(gpsUploadTime);
		csvStringBuilder.append(split);
		// 坐标只返回小数点后6位
		String strX = StringUtil.formatDouble(this.getX(), CoordFormat);
		// index:5
		csvStringBuilder.append(strX);
		csvStringBuilder.append(split);
		String strY = StringUtil.formatDouble(this.getY(), CoordFormat);
		// index:6
		csvStringBuilder.append(strY);
		csvStringBuilder.append(split);
		String strReviseX = StringUtil.formatDouble(this.getReviseX(), CoordFormat);
		// index:7
		csvStringBuilder.append(strReviseX);
		csvStringBuilder.append(split);
		String strReviseY = StringUtil.formatDouble(this.getReviseY(), CoordFormat);
		// index:8
		csvStringBuilder.append(strReviseY);
		csvStringBuilder.append(split);
		// index:9
		csvStringBuilder.append(this.getGpsTag());
		csvStringBuilder.append(split);
		// index:10
		csvStringBuilder.append(this.getSpeed());
		csvStringBuilder.append(split);
		// index:11
		csvStringBuilder.append(this.getSpeedLimit());
		csvStringBuilder.append(split);
		// index:12
		csvStringBuilder.append(this.getPlateNumber());
		csvStringBuilder.append(split);
		// index:13
		csvStringBuilder.append(this.getStatus());
		csvStringBuilder.append(split);
		// index:14
		csvStringBuilder.append(this.getAccuracy());
		csvStringBuilder.append(split);
		// index:15
		csvStringBuilder.append(this.getDirection());
		csvStringBuilder.append(split);
		// index:16
		csvStringBuilder.append(this.getDeleteTag());
		csvStringBuilder.append(split);
		// index:17
		csvStringBuilder.append(this.getGroupId());
		return csvStringBuilder.toString();
	}

	public static GPSPoint parseCSVString(String csvString) {
		GPSPoint gpsPoint = null;
		try {
			String[] arr = csvString.split(StringUtil.COMMA);
			gpsPoint = new GPSPoint(Double.parseDouble(arr[5]), Double.parseDouble(arr[6]));

			gpsPoint.setAccountId(arr[0]);
			gpsPoint.setLoginMobile(arr[1]);
			gpsPoint.setAddress(arr[2]);
			try {
				gpsPoint.setGPSTime(DateUtil.getGPSTimeFormat().parse(arr[3]));
			} catch (Exception e) {
				String message = "解析GPSTime（" + arr[3] + "）失败。";
				LOGGER.info(message, e);
			}
			try {
				if (arr[4] != null && arr[4].length() > 0) {
					gpsPoint.setUploadTime(DateUtil.getGPSTimeFormat().parse(arr[4]));
				}
			} catch (Exception e) {
				String message = "解析UploadTime（" + arr[4] + "）失败。";
				LOGGER.info(message, e);
			}
			try {
				gpsPoint.setReviseX(Double.parseDouble(arr[7]));
			} catch (Exception e) {
				String message = "解析ReviseX（" + arr[7] + "）失败。";
				LOGGER.info(message, e);
			}
			try {
				gpsPoint.setReviseY(Double.parseDouble(arr[8]));
			} catch (Exception e) {
				String message = "解析ReviseY（" + arr[8] + "）失败。";
				LOGGER.info(message, e);
			}
			try {
				gpsPoint.setGpsTag(Integer.parseInt(arr[9]));
			} catch (Exception e) {
				String message = "解析GpsTag（" + arr[9] + "）失败。";
				LOGGER.info(message, e);
			}
			try {
				gpsPoint.setSpeed(Double.parseDouble(arr[10]));
			} catch (Exception e) {
				String message = "解析Speed（" + arr[10] + "）失败。";
				LOGGER.info(message, e);
			}
			try {
				gpsPoint.setSpeedLimit(Double.parseDouble(arr[11]));
			} catch (Exception e) {
				String message = "解析SpeedLimit（" + arr[11] + "）失败。";
				LOGGER.info(message, e);
			}
			gpsPoint.setPlateNumber(arr[12]);
			try {
				gpsPoint.setStatus(Integer.parseInt(arr[13]));
			} catch (Exception e) {
				String message = "解析Status（" + arr[13] + "）失败。";
				LOGGER.info(message, e);
			}
			try {
				gpsPoint.setAccuracy(Integer.parseInt(arr[14]));
			} catch (Exception e) {
				String message = "解析Accuracy（" + arr[14] + "）失败。";
				LOGGER.info(message, e);
			}
			try {
				gpsPoint.setDirection(Double.parseDouble(arr[15]));
			} catch (Exception e) {
				String message = "解析Direction（" + arr[15] + "）失败。";
				LOGGER.info(message, e);
			}
			if (arr[16] == null || arr[16].length() == 0 || arr[16].contains(StringUtil.NULL)) {
				gpsPoint.setDeleteTag(null);
			} else {
				gpsPoint.setDeleteTag(arr[16]);
			}
			if (arr.length >= 18) {
				gpsPoint.setGroupId(arr[17]);
			}
		} catch (Exception ex) {
			LOGGER.debug("解析csvString发生异常", ex);
		}

		return gpsPoint;
	}

	@Override
	public int hashCode() {
		return this.toString().hashCode();
	}

	@Override
	public boolean equals(Object object) {
		if (object == null || !object.getClass().equals(GPSPoint.class)) {
			return false;
		}

		GPSPoint gpsPoint = (GPSPoint) object;
		return (this.x == gpsPoint.x) && (this.y == gpsPoint.y) && (this.reviseX == gpsPoint.reviseX) && (this.reviseY == gpsPoint.reviseY)
				&& ((this.plateNumber == null && gpsPoint.plateNumber == null) || (this.plateNumber != null && this.plateNumber.equals(gpsPoint.plateNumber)))
				&& ((this.accountId == null && gpsPoint.accountId == null) || (this.accountId != null && this.accountId.equals(gpsPoint.accountId)))
				&& ((this.groupId == null && gpsPoint.groupId == null) || (this.groupId != null && this.groupId.equals(gpsPoint.groupId)))
				&& ((this.loginMobile == null && gpsPoint.loginMobile == null) || (this.loginMobile != null && this.loginMobile.equals(gpsPoint.loginMobile)))
				&& ((this.address == null && gpsPoint.address == null) || (this.address != null && this.address.equals(gpsPoint.address)))
				&& ((this.gpsTime == null && gpsPoint.gpsTime == null) || (this.gpsTime != null && this.gpsTime.equals(gpsPoint.gpsTime)))
				&& ((this.uploadTime == null && gpsPoint.uploadTime == null) || (this.uploadTime != null && this.uploadTime.equals(gpsPoint.uploadTime)))
				&& (this.direction == gpsPoint.direction) && (this.speed == gpsPoint.speed) && (this.speedLimit == gpsPoint.speedLimit)
				&& (this.order == gpsPoint.order) && (this.gpsTag == gpsPoint.gpsTag) && (this.status == gpsPoint.status)
				&& (this.accuracy == gpsPoint.accuracy)
				&& ((this.deleteTag == null && gpsPoint.deleteTag == null) || (this.deleteTag != null && this.deleteTag.equals(gpsPoint.deleteTag)));
	}
}
